package com.slliver.controller;


import com.alibaba.csp.sentinel.Entry;
import com.alibaba.csp.sentinel.SphO;
import com.alibaba.csp.sentinel.SphU;
import com.alibaba.csp.sentinel.Tracer;
import com.alibaba.csp.sentinel.slots.block.BlockException;
import com.alibaba.csp.sentinel.slots.block.RuleConstant;
import com.alibaba.csp.sentinel.slots.block.flow.FlowRule;
import com.alibaba.csp.sentinel.slots.block.flow.FlowRuleManager;
import lombok.extern.slf4j.Slf4j;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;

import javax.annotation.PostConstruct;
import java.util.ArrayList;
import java.util.List;

@Slf4j
@RestController
@RequestMapping("/sentinel/test")
public class TestController {


    private static final String RESOURCE_NAME = "hello";

    // 进行sentinel流量控制
    @GetMapping("/hello")
    public String hello(){
        // 定义一个资源
        Entry entry = null;
        try {
            // sentinel是针对资源进行限制的(通畅资源名称和请求的地址名称一样)
            entry = SphU.entry(RESOURCE_NAME);
            // 被保护的业务逻辑
            String msg  = "我的业务逻辑代码，被sentinel流量保护了，我安全了";
            log.info("success msg ===>>" + msg);
            return msg;
        }catch (BlockException be){
            log.error("block error msg...", be);
            return "Block msg == >> 被限制流量访问了，被流量控制了，怎么办";
        }catch (Exception ex){
            // 如果需要配置降级规则，需要通过这种方式记录业务异常
            Tracer.traceEntry(ex, entry);
        }finally {
            if(entry != null){
                entry.exit();
            }
        }
        return "hello sentinel...";
    }


    /**
     * 为各种受保护的资源进行各种规则设置
     */
    @PostConstruct  // spring加载bean的时候调用此方法
    private static void initFlowRules(){

        // 通过代码定义流量控制规则
        // 流控规则
        List<FlowRule> rules = new ArrayList<>();

        // 定义一个流程
        FlowRule rule = new FlowRule();
        // 设置受流量控制保护的资源(这里就是我们的hello)
        rule.setResource(RESOURCE_NAME);
        // 设置流控规则QPS
        rule.setGrade(RuleConstant.FLOW_GRADE_QPS);
        // 设置受保护的资源阈值，简单的说 每秒可以被访问的次数
        // Set limit QPS to 20
        rule.setCount(1);
        rules.add(rule);

        // 加载配置好的规则
        FlowRuleManager.loadRules(rules);
    }


}
